#pragma once

#include <string>
#include <unordered_map>
#include <memory>

class Room;
typedef std::shared_ptr<Room> RoomPtr;

class RoomManager;
typedef std::shared_ptr<RoomManager> RoomManagerPtr;

class RoomManager
{
public:
	static RoomManagerPtr getSingleton();
	RoomManager();
	~RoomManager();

	void init(const std::string &path);

	const RoomPtr &getSpawn() const { return spawn_room; }

protected:
	struct TempExitData
	{
		std::string direction;
		unsigned int room_id;
		std::string description;
		std::vector<unsigned int> settings; //Exit::Settings is undefined in this scope, so we identify by unsigned int
		TempExitData() : room_id(0) {}
	};

	struct TempRoomData
	{
		std::string description;
		TempExitData w, n, e, s, u, d;
		std::vector<unsigned int> settings; //Room::Settings is undefined in this scope, so we identify by unsigned int
		std::vector<unsigned int> item_ids;
	};
	typedef std::unique_ptr<TempRoomData> TempRoomDataPtr;

	void parseDescription(const std::vector<std::string> &lines, unsigned int &index, std::string &description);

	void parseExits(const std::vector<std::string> &lines, unsigned int &index, TempRoomDataPtr &data);
	void parseExitLine(const std::vector<std::string> &lines, unsigned int &index, TempRoomDataPtr &data);
	void parseExitHeader(const std::string &line, std::string &direction, unsigned int &id);
	void parseExitContent(const std::vector<std::string> &lines, unsigned int &index, TempExitData &data);
	void linkExits(std::unordered_map<unsigned int, RoomPtr>::iterator &it);

    void parseItems(const std::vector<std::string> &lines, unsigned int &index, TempRoomDataPtr &data);
    void spawnItems(std::unordered_map<unsigned int, RoomPtr>::iterator &it);

	void parseMonsters(const std::vector<std::string> &lines, unsigned int &index, TempRoomDataPtr &data);
	void parseSpecials(const std::vector<std::string> &lines, unsigned int &index, TempRoomDataPtr &data);

	void parseSettings(const std::vector<std::string> &lines, unsigned int &index, std::vector<unsigned int> &settings);
	void applySettings(std::unordered_map<unsigned int, RoomPtr>::iterator &it);

	static RoomManagerPtr singleton;
	std::unordered_map<unsigned int, RoomPtr> rooms;
	std::unordered_map<unsigned int, TempRoomDataPtr> temp_room_data;
	RoomPtr spawn_room;
	RoomPtr null_room;
};
